﻿using AutoMapper;
using HamcoWcs.Contract;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.Contract.ContractPcon;
using HamcoWcs.Contract.ContractSrm;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.SubTasks;
using HamcoWcs.Entitys.WcsLocations;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.DeviceMsgs.SrmMsgs;
using HamcoWcs.Models.Devices;
using HamcoWcs.Models.MainTasks;
using HamcoWcs.Models.TibcoMessage;
using HamcoWcs.Models.SubTasks;
using HamcoWcs.Models.WcsLocations;
using HamcoWcs.Service.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HamcoWcs.Contract.ContractPcon.IPconDbMsgParsers;

namespace HamcoWcs.Service.Srm
{
    [AutoInject(typeof(ISrmMsgService), InjectType.Scope)]
    public class SrmMsgService : ScopeServiceBase, ISrmMsgService
    {
        private readonly ILoggerService _loggerService;
        private readonly IBaseTaskService _baseTaskService;
        private readonly IPathService _pathService;
        private readonly IPconBaseService _pconBaseService;
        private readonly IMesCommunicateService _mesCommunicateService;

        public SrmMsgService(IMapper mapper, IServiceScopeFactory scopeFactory,
            WcsDbContext wcsDbContext, ILoggerService loggerService,
            IBaseTaskService baseTaskService, IPathService pathService,
            IPconBaseService pconBaseService,
            IMesCommunicateService mesCommunicateService)
            : base(wcsDbContext, mapper)
        {
            _loggerService = loggerService;
            _baseTaskService = baseTaskService;
            _pathService = pathService;
            _pconBaseService = pconBaseService;
            _mesCommunicateService = mesCommunicateService;
        }


        //public void DealRecvMsg(SrmDto srm, SrmRecvMsg msgDto)
        //{


        //    if (msgDto.Request == 1)
        //    {
        //        //取货完成
        //        DealPickFinishMsg(srm, msgDto);
        //    }
        //    else if (msgDto.Request == 2)
        //    {
        //        //任务完成完成
        //        //查找相应任务对象
        //        DealTaskFinishMsg(srm, msgDto);
        //    }
        //}

        public SubTask FindSrmTask(SrmPlc srmPlc)
        {
            throw new NotImplementedException();
            //if (srmPlc.IsGoods == 1)
            //{
            //    return _wcsDbContext.SubTasks
            //                        .AsNoTracking()
            //                        .Where(x => x.PlcName == srmPlc.PlcName)
            //                        .Where(x => x.UnitId == srmPlc.UnitId)
            //                        .Include(x => x.MainTask)
            //                        .FirstOrDefault();
            //}
            //else
            //{
            //    // todo 就近原则添加
            //    // todo 优先级确认
            //    // todo 分段搬送（双机模式中转）
            //    // todo 锁定时禁用部分
            //    var onProgressTask = _wcsDbContext.SubTasks
            //                                      .AsNoTracking()
            //                                      .Where(x => x.PlcName == srmPlc.PlcName)
            //                                      .Where(x => x.TaskStatus == EnumSubTaskStatus.OnProgress.ToString())
            //                                      .Include(x => x.MainTask)
            //                                      .FirstOrDefault();
            //    if (onProgressTask != null) return onProgressTask;

            //    var mainTasks = _wcsDbContext.MainTasks
            //                                 .Include(x => x.SubTasks)
            //                                 .Where(x => x.SubTasks.Any(
            //                                     s => s.PlcName == srmPlc.PlcName &&
            //                                          s.TaskStatus == EnumSubTaskStatus.Ready.ToString()))
            //                                 .OrderByDescending(x => x.Priority)
            //                                 .ThenByDescending(x => x.CreatedTime)
            //                                 .ToList();

            //    if (!mainTasks.Any()) return null;

            //    var mainTaskDtos = _mapper.Map<List<MainTaskDto>>(mainTasks);

            //    foreach (var mainTaskDto in mainTaskDtos)
            //    {
            //        var nodeInfo = _wcsDbContext.NodeInfos.FirstOrDefault(x => x.NodeName == mainTaskDto.FromLoc);
            //        var task = mainTaskDto.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready);


            //        if (task.FromLoc.Length > 5)
            //            mainTaskDto.Distance = Math.Abs(srmPlc.CurrentBay - int.Parse(task.FromLoc.Substring(3, 4)));//出库 判断货位到堆垛机的距离
            //        else
            //            //mainTaskDto.Distance = Math.Abs(srmPlc.CurrentBay - nodeInfo.Bay);//入库  判断站台到堆垛机的距离

            //            mainTaskDto.Distance = Math.Abs(srmPlc.CurrentBay - 0);//入库  判断站台到堆垛机的距离
            //        throw new NotImplementedException();
            //    }

            //    mainTaskDtos = mainTaskDtos.OrderByDescending(x => x.Priority)
            //                               .ThenBy(x => x.Distance)
            //                               .ToList();


            //    //srmPlc.CurrentBay
            //    foreach (var maintask in mainTasks)
            //    {
            //        var task = maintask.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString());
            //        if (task == null)
            //        {
            //            continue;
            //        }
            //        if (IsTaskCanDo(task))
            //            return task;
            //    }
            //    return null;
            //}
        }



        private string GetStationName(string nodeName)
        {
            var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WmsLocName == nodeName);
            //var node = _pathService.GetWmsNode(nodeName);

            return loc?.SrmName ?? "0";
        }

        private PconDto GetPcon(string srmstation)
        {
            //var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WmsLocName == srmstation);
            //var node = _pathService.GetWmsNode(srmstation);
            //return node;
            // todo 获取SRM对应节点设备信息
            //var node = _pathService.GetSrmNode(srmstation);
            //if (node == null)
            //    node = _pathService.GetWcsNode(srmstation);
            //if (node == null)
            //    return null;
            //var pconplc = _pconBaseService.GetPconPlc(node.PlcName);
            //if (!pconplc.Pcons.ContainsKey(int.Parse(node.NodeName)))
            //    return null;
            //return pconplc.Pcons[int.Parse(node.NodeName)];
            return null;
        }

        // todo 需要在双轨模式时需要判断堆垛机位置能否下发命令
        // todo 堆垛机锁定后需要新增字段判断货架是否无法到达
        private bool IsTaskCanDo(SubTask task)
        {
            if (task.SubTaskType == EnumSubTaskType.SrmOutTask.ToString())
            {
                //出库任务，检查出库站台
                var station = GetPcon(task.ToLoc);
                if (station == null || station.IsGoods == 1 || station.PconMode != 1)
                {
                    return false;
                }
            }
            else if (task.SubTaskType == EnumSubTaskType.SrmInTask.ToString())
            {
                //入库任务，检查入库站台
                var station = GetPcon(task.FromLoc);
                if (station == null || station.PconMode != 1 || station.IsGoods == 0 || station.UnitId != task.UnitId)
                {
                    return false;
                }
            }
            else if (task.SubTaskType == EnumSubTaskType.SrmStraightOutTask.ToString())
            {
                //直出任务，检查入库站台与出库站台
                var fstation = GetPcon(task.FromLoc);
                if (fstation == null || fstation.PconMode != 1 || fstation.IsGoods == 0 || fstation.UnitId != task.UnitId)
                {
                    return false;
                }
                var tstation = GetPcon(task.ToLoc);
                if (tstation == null || tstation.IsGoods == 1 || tstation.PconMode != 1)
                {
                    return false;
                }
            }
            return true;

        }
        private LocStationInfo GetLocStationInfo(string locName)
        {
            var locstation = new LocStationInfo();
            //var node = GetPcon(locName);
            var station = GetStationName(locName);

            if (station == "0" || string.IsNullOrEmpty(station))
            {
                var flocInfo = locName.ToLocationInfo();
                var location = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == flocInfo.Name);
                if (location != null)
                {
                    locstation.Row = (ushort)location.Row;
                    locstation.Bay = (ushort)location.Bay;
                    locstation.Lev = (ushort)location.Lev;
                    locstation.Deep = (ushort)flocInfo.Depth;
                }
            }
            else
            {
                locstation.Station = ushort.Parse(station);
            }

            //if (node != null)
            //{
            //    locstation.Station = ushort.Parse(locName);
            //}
            //else
            //{
            //    var flocInfo = locName.ToLocationInfo();
            //    var location = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == flocInfo.Name);
            //    if (location != null)
            //    {
            //        locstation.Row = (ushort)location.Row;
            //        locstation.Bay = (ushort)location.Bay;
            //        locstation.Lev = (ushort)location.Lev;
            //        locstation.Deep = (ushort)flocInfo.Depth;
            //    }

            //}
            return locstation;
        }

        public SrmSendMsg GetSrmRecorveryMsg()
        => new SrmSendMsg( false)
        {
            Request = (ushort)EnumSrmSendMsg.AllowRecoveryRequest,
        };

        public SrmSendMsg GetSrmSendMsg(SubTask task)
        {
            //var taskDto = _mapper.Map<SubTaskDto>(task);
            var fstation = GetLocStationInfo(task.FromLoc);
            var tstation = GetLocStationInfo(task.ToLoc);

            return new SrmSendMsg(fstation, tstation, false)
            {
                UnitId = task.UnitId,
                Request = GetRequestFlag(task.SubTaskType),
            };
        }

        public SrmSendMsg GetHandOffMsg(SubTask task)
        {
            var fstation = GetLocStationInfo(task.FromLoc);
            var tstation = GetLocStationInfo(task.HandOffShelf);

            var request = "";
            if (task.FromLoc.IsShelf())
            {
                request = EnumSubTaskType.SrmMoveTask.ToString();
            }
            else
            {
                request = EnumSubTaskType.SrmInTask.ToString();
            }

            return new SrmSendMsg(fstation, tstation, false)
            {
                UnitId = task.UnitId,
                Request = GetRequestFlag(request),
            };
        }

        private ushort GetRequestFlag(string subtaskType)
        {
            switch (Enum.Parse<EnumSubTaskType>(subtaskType))
            {
                case EnumSubTaskType.SrmInTask: return 1;
                case EnumSubTaskType.SrmOutTask: return 2;
                case EnumSubTaskType.SrmMoveTask: return 3;
                case EnumSubTaskType.SrmStraightOutTask: return 4;
                case EnumSubTaskType.SrmInventoryTask: return 10;
                case EnumSubTaskType.SrmAbnormalInboundTask: return 16;
                case EnumSubTaskType.SrmAbnormalOutboundTask: return 17;
            }
            return 0;
        }
    }
}
